import { isReservedTag, isObject } from "../utils.js"

//创建元素的虚拟dom
export function createElement(vm, tag, data = {}, ...children) {
    //console.log(tag);
    //需要对标签名做过滤 因为标签名可能是一个自定义组件
    if (isReservedTag(tag)) {
        //不同的tag标签
        return vnode(vm, tag, data, data.key, children, undefined)
    } else {
        //组件 
        const Ctor = vm.$options.components[tag];//Ctor可能是对象/构造函数
        //console.log(vm.$options.components);
        //console.log(Ctor);
        //创建组件vnode
        return createComponent(vm, tag, data, data.key, children, Ctor)
    }
}
//定义创建组件vnode函数
function createComponent(vm, tag, data, key, children, Ctor) {
    //vm当前Vue实例
    //tag 组件名标签(<my-button></my-button>)
    //data 
    //key 属性名
    //children 插槽
    //判断Ctor是否为对象
    if (isObject(Ctor)) {
        //是对象,extend函数就将Ctor对象转化成Ctor构造函数 
        Ctor = vm.$options._base.extend(Ctor)
    }
    //console.log(Ctor);
    //给组件增加生命周期
    data.hook = {
        init(vnode) {
            //调用子组件的构造函数
            let child = vnode.componentInstance = new vnode.componentOptions.Ctor({})
            //debugger
            child.$mount();//手动挂载 child.$el=vnode.componentInstance.$el=真实的元素
        }//初始化钩子
    }

    //组件vnode和普通虚拟vnode的不同点
    //组件的虚拟节点: 拥有hook 和 当前组件的componentOptions中存放了 组件的构造函数

    //console.log(vnode(vm, `vue-component-${Ctor.cid}-${tag}`, data, key, undefined, undefined, { Ctor }));
    //debugger
    return vnode(vm, `vue-component-${Ctor.cid}-${tag}`, data, key, undefined, undefined, { Ctor })
    //console.log(Ctor);

}
//创建文本的虚拟dom
//debugger
export function createTextVnode(vm, text) {
    return vnode(vm, undefined, undefined, undefined, undefined, text)
}
//虚拟dom
function vnode(vm, tag, data, key, children, text, componentOptions) {
    return {
        vm,
        tag,
        data,
        key,
        children,
        text,
        componentOptions
    }
}
//判断是非是相同的节点,根据:key值来判断
export function isSameVnode(oldVnode, newVnode) {
    //判断新旧节点的标签/绑定的key值是否相等
    return (oldVnode.tag === newVnode.tag) && (oldVnode.key === newVnode.key)
}